/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-05
 * V4.0
 */
package com.jphenix.servlet.common;

import com.jphenix.driver.json.Json;
import com.jphenix.servlet.filter.FilterExplorer;
import com.jphenix.servlet.filter.SecureRequestWrapper;
import com.jphenix.share.lang.*;
import com.jphenix.share.util.DebugUtil;
import com.jphenix.share.util.StringUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.servlet.IFakeRequest;
import com.jphenix.standard.servlet.IRequest;
import com.jphenix.standard.viewhandler.IViewHandler;
import com.jphenix.webserver.instancea.ServeConnection;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.security.Principal;
import java.util.*;

/**
 * 封装后的页面请求对象
 * 
 * 该类只实现了重现指定外部动作时的参数
 * 用于前台调用返回功能
 * 
 * 注意：getServletPath()和getPathInfo()只能一个有值，一个返回空，否则Tomcat读取静态文件会提示找不到目标文件。
 *      我们发现Tomcat中getPathInfo()永远返回空，我们也针对这种情况不再对getPathInfo做处理
 * 
 * 2019-08-19 优化了读入流缓存
 * 2019-08-23 为虚拟动作路径过滤器增加了相关的方法
 * 2019-08-24 去掉了setPathTranslated方法，getPathTranslated方法直接由网站根路径加上pathInfo实现，提高效率
 * 2019-08-26 整合了getServletPath和getPathInfo方法，在这个架构中，这两个方法返回的内容是一样的
 * 2019-08-31 不再处理getPathInfo，再tomcat该方法永远返回空
 * 2019-09-17 getHeader返回值绝对不等于null
 * 2019-09-18 不能让  getHeader返回值绝对不等于null ！！ 可以返回null，否则Tomcat报412错误
 * 2019-12-26 修改了web.xml中配置虚拟路径时，导致无法访问的错误
 * 2020-06-30 在构造函数中，将FilterExplorer类实例传入其中
 *            在获取当前请求路径中，增加了从配置文件中获取根URL，防止请求头被篡改，返回其它地址URL
 * 2020-07-18 增加了重复获取请求数据调试方法
 * 2020-08-20 构建请求编码变量时，不设置默认编码格式
 * 2021-03-17 适配tomcat9中的 servlet-api.jar
 * 
 * @author 刘虻
 * 2010-7-1 下午06:49:27
 */
@ClassInfo({"2021-03-17 20:52","封装后的页面请求对象"})
public class HttpServletRequestImpl implements IRequest,IFakeRequest {

	//如果插件声明了虚拟路径，在调用动作之前应该去掉servletPath中的插件虚拟路径
	protected String                           servletPath        = null; //动作路径
	
	protected HttpServletRequest               httpServletRequest = null; //核心类
	
	protected WebParameterMap<String,String[]> parameterMap       = null; //用于被覆盖的参数容器
	
	protected Map<String,String>               urlParameterMap    = null; //请求URL中的参数对照容器
	
	private   boolean                          buffered           = false; //是否缓存提交值
  
	//是否为假的页面反馈
	//用clone或者ewInstance方法 构造的当前类，该值为true
	private boolean                            isFake             = false;
	
	private byte[]             dataBuffers          = null;    //缓存数据流
	private ServletInputStream bufferIs             = null;    //缓存对象
	private HttpSession        session              = null;    //Servlet会话
	private String             webBasePath          = null;    //网站根路径
	private String             queryString          = null;    //提交的参数
	private List<String>       customHeaderNameList = null;    //自定义头主键序列
	private List<String>       pubHeaderNameList    = null;    //系统头主键序列
	private String             contextPath          = null;    //虚拟路径
	private int                localPort            = 0;       //本地服务监听端口
	private String             authType             = null;    //母鸡
	private Map<String,String> headerMap            = null;    //头信息
	private String             method               = null;    //方法
	private String             contentType          = null;    //内容类型
	private String             characterEncoding    = null;    //编码格式
	private String             scheme               = null;    //方案 http https
	private Map<String,Object> fakeAttributeMap     = null;    //属性容器（仿造对象中有效）
	private Locale             locale               = null;    //母鸡
	private String             protocol             = null;    //协议
	private boolean            secure               = false;   //是否为安全的母鸡
	private FilterExplorer     fe                   = null;    //过滤器入口
	private boolean            firstGetReqData      = true;    //是否首次获取请求数据
	private String             reqDataTraceInfo     = null;    //首次获取提交报文体数据的堆栈信息

	
	/**
	 * 构造函数
	 * @author 刘虻
	 */
	public HttpServletRequestImpl(
			HttpServletRequest httpServletRequest) {
		super();
		if(httpServletRequest==null) {
			isFake = true;
			method = "POST";
			scheme = "http";
			protocol = "HTTP/1.1";
			localPort = 80;
			fakeAttributeMap = new HashMap<String,Object>();
			return;
		}
		this.httpServletRequest = httpServletRequest;
	}
	
	
	/**
     * 构造函数
     * 由过滤器管理类传入contextPath，因为将框架植入现有系统中
     * 在web.xml中设置了指定路径后触发，比如：<url-pattern>/jp/*</url-pattern>
     * 那么/jp也应该是虚拟路径，所以在过滤器管理类中，读取到这个路径，拼装成
     * 改装后的contextPath
     * @author 刘虻
     */
    public HttpServletRequestImpl(
            HttpServletRequest httpServletRequest,FilterExplorer fe,String contextPath) {
        super();
        if(httpServletRequest==null) {
            isFake = true;
            method = "POST";
            scheme = "http";
            protocol = "HTTP/1.1";
            localPort = 80;
            fakeAttributeMap = new HashMap<String,Object>();
            return;
        }
        this.httpServletRequest = httpServletRequest;
        this.contextPath        = contextPath;
        this.fe                 = fe;
    }
    
    
    /**
     * 构造函数
     * @author MBG
     */
	public HttpServletRequestImpl(
			IRequest httpServletRequest,FilterExplorer fe,boolean isFake) {
		super();
		if(httpServletRequest==null) {
			this.isFake = true;
		}else {
			this.isFake = isFake;
			authType = httpServletRequest.getAuthType();
			method = httpServletRequest.getMethod();
			contentType = httpServletRequest.getContentType();
			characterEncoding = httpServletRequest.getCharacterEncoding(); 
			localPort = httpServletRequest.getLocalPort();
			scheme = httpServletRequest.getScheme();
			protocol = httpServletRequest.getProtocol();
			secure = httpServletRequest.isSecure();
			this.httpServletRequest = httpServletRequest;
		}
		if(characterEncoding==null || characterEncoding.length()<1) {
			characterEncoding =  "UTF-8";
		}
		if(isFake) {
			method = "POST";
			scheme = "http";
			protocol = "HTTP/1.1";
			localPort = 80;
			fakeAttributeMap = new HashMap<String,Object>();
			headerMap = new HashMap<String,String>();
			if(httpServletRequest!=null) {
				//获取头名称枚举
				Enumeration<String> names = httpServletRequest.getHeaderNames();
				if(names!=null) {
					String key; //主键
					while(names.hasMoreElements()) {
						key = names.nextElement();
						headerMap.put(key,httpServletRequest.getHeader(key));
					}
				}
			}
		}
		this.fe = fe;
	}
	
	/**
	 * 获取核心类
	 * @return 核心类
	 * 2014年12月3日
	 * @author 马宝刚
	 */
	public HttpServletRequest getKernel() {
	    return httpServletRequest;
	}
	
	/**
	 * 设置会话信息
	 * @param session 会话信息类
	 * 2014年9月11日
	 * @author 马宝刚
	 */
	public void setSession(HttpSession session) {
	    this.session = session;
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getAuthType() {
		if(authType==null) {
			authType = httpServletRequest.getAuthType();
		}
		return authType;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getContextPath() {
		if(contextPath==null) {
			contextPath = SString.valueOf(httpServletRequest.getContextPath());
		}
		return contextPath;
	}

	/**
	 * 设置上下文路径
	 * @param contextPath 上下文路径
	 * 2019年8月22日
	 * @author MBG
	 */
	public void setContextPath(String contextPath) {
		this.contextPath = contextPath;
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public Cookie[] getCookies() {
		if(isFake) {
			return null; //不支持复杂方法
		}
		return httpServletRequest.getCookies();
	}
	
	/**
	 * 获取指定的Cookie值
	 * @param key 主键
	 * @return 值
	 * 2017年3月1日
	 * @author MBG
	 */
	@Override
    public String getCookieValue(String key) {
		if(key==null) {
			return "";
		}
		//获取Cookie数组
		Cookie[] cookies = getCookies();
		if(cookies==null || cookies.length<1) {
			return "";
		}
		for(int i=0;i<cookies.length;i++) {
			if(key.equals(cookies[i].getName())) {
				return SString.valueOf(cookies[i].getValue());
			}
		}
		return "";
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public long getDateHeader(String arg0) {
		if(isFake) {
			return SLong.valueOf(headerMap.get(arg0));
		}
		return httpServletRequest.getDateHeader(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getHeader(String arg0) {
		if(isFake) {
			return SString.valueOf(headerMap.get(arg0));
		}
		//注意：不能在这里强制转换成空字符串，否则Tomcat输出时会报412错误
		return httpServletRequest.getHeader(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    @SuppressWarnings("unchecked")
	public Enumeration<String> getHeaderNames() {
		if(isFake) {
			return new SEnumeration<String>(headerMap);
		}
		return httpServletRequest.getHeaderNames();
	}
	
	
	/**
	 * 获取公共头主键序列（注意：该方法只是为了区别出自定义头主键）
	 * @return 公共头主键序列
	 * 2016年7月13日
	 * @author MBG
	 */
	public List<String> getPubHeaderNameList(){
		if(pubHeaderNameList==null) {
			pubHeaderNameList = new ArrayList<String>();
			
			pubHeaderNameList.add("accept");
			pubHeaderNameList.add("Accept-Charse");
			pubHeaderNameList.add("accept-encoding");
			pubHeaderNameList.add("Accept-Encoding");
			pubHeaderNameList.add("accept-language");
			pubHeaderNameList.add("Accept-Language");
			pubHeaderNameList.add("Access-Control-Allow-Origin");
			pubHeaderNameList.add("Accept-Ranges");
			pubHeaderNameList.add("Age");
			pubHeaderNameList.add("Authorization");
			pubHeaderNameList.add("cache-control");
			pubHeaderNameList.add("Cache-Control");
			pubHeaderNameList.add("connection");
			pubHeaderNameList.add("Connection");
			pubHeaderNameList.add("Content-Disposition");
			pubHeaderNameList.add("Content-Encoding");
			pubHeaderNameList.add("Content-Length");
			pubHeaderNameList.add("Content-Type");
			pubHeaderNameList.add("Content-Range");
			pubHeaderNameList.add("Content-Language");
			pubHeaderNameList.add("cookie");
			pubHeaderNameList.add("Cookie");
			pubHeaderNameList.add("Date");
			pubHeaderNameList.add("ETag");
			pubHeaderNameList.add("Expires");
			pubHeaderNameList.add("host");
			pubHeaderNameList.add("Host");
			pubHeaderNameList.add("If-Match");
			pubHeaderNameList.add("If-None-Match");
			pubHeaderNameList.add("If-Modified-Since");
			pubHeaderNameList.add("If-Unmodified-Since");
			pubHeaderNameList.add("If-Range");
			pubHeaderNameList.add("Last-Modified");
			//pubHeaderNameList.add("Location"); //该参数属于自定义，否则该值如果被屏蔽掉，就不会自动跳转了
			pubHeaderNameList.add("P3P");
			pubHeaderNameList.add("Pragma");
			pubHeaderNameList.add("Proxy-Authenticate");
			pubHeaderNameList.add("Proxy-Authorization");
			pubHeaderNameList.add("Range");
			pubHeaderNameList.add("Referer");
			pubHeaderNameList.add("Server");
			pubHeaderNameList.add("server");
			pubHeaderNameList.add("Set-Cookie");
			pubHeaderNameList.add("Transfer-Encoding");
			pubHeaderNameList.add("upgrade-insecure-requests");
			pubHeaderNameList.add("user-agent");
			pubHeaderNameList.add("Vary");
			pubHeaderNameList.add("Via");
		}
		return pubHeaderNameList;
	}
	
	
	
	/**
	 * 获取自定义头主键序列
	 * @return 自定义头主键序列
	 * 2016年7月13日
	 * @author MBG
	 */
	@Override
    public List<String> getCustomHeaderNameList(){
		if(customHeaderNameList==null) {
			customHeaderNameList = new ArrayList<String>();
			getPubHeaderNameList(); //初始化一下，在下面就可以直接使用变量了
			//获取全部头主键
			Enumeration<String> headerNames = getHeaderNames();
			String key; //头主键
			while(headerNames.hasMoreElements()) {
				key = headerNames.nextElement();
				if(key==null || pubHeaderNameList.contains(key)) {
					continue;
				}
				customHeaderNameList.add(key);
			}
		}
		return customHeaderNameList;
	}
	
	
	/**
	 * 获取自定义头信息容器
	 * @return 自定义头信息容器
	 * 2016年7月13日
	 * @author MBG
	 */
	@Override
    public Map<String,String> getCustomHeaderMap(){
		Map<String,String> reMap = new HashMap<String,String>();
		for(String key:getCustomHeaderNameList()) {
			reMap.put(key,getHeader(key));
		}
		return reMap;
	}
	
	
	
	
	/**
	 * 获取提交数据字节数组
	 * @return 提交数据字节数组
	 * 2014年9月5日
	 * @author 马宝刚
	 */
	@Override
    public byte[] getPostData() {
	    if("post".equalsIgnoreCase(getMethod())) {
	        setBuffered(); //设置为缓存提交数据，否则执行完该方法，随后在获取post参数时就会报错
	        try {
	            getInputStream(); //在标记缓存提交数据后，获取一次流，将会将提交值缓存到变量中
	        }catch(Exception e) {
	            e.printStackTrace();
	        }
	        return dataBuffers;
	    }
	    return null;
	}
	
	/**
	 * 获取头信息容器
	 * @return 头信息容器
	 * 2014年9月5日
	 * @author 马宝刚
	 */
	@Override
    public Map<String,String> getHeaderMap(){
		if(headerMap==null) {
			headerMap = new HashMap<String,String>();
		    //获取头主键枚举
		    Enumeration<String> headerNames = getHeaderNames();
		    if(headerNames!=null) {
	    	    String key; //头信息主键
	    	    while(headerNames.hasMoreElements()) {
	    	        key = headerNames.nextElement();
	    	        headerMap.put(key,getHeader(key));
	    	    }
		    }
		}
	    return headerMap;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    @SuppressWarnings("unchecked")
	public Enumeration<String> getHeaders(String arg0) {
		if(isFake) {
			if(headerMap==null) {
				return null;
			}
			return new SEnumeration<String>(headerMap.get(arg0));
		}
		return httpServletRequest.getHeaders(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public int getIntHeader(String arg0) {
		if(isFake) {
			if(headerMap==null) {
				return 0;
			}
			return SInteger.valueOf(headerMap.get(arg0));
		}
		return httpServletRequest.getIntHeader(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getMethod() {
		if(isFake) {
			return method;
		}
		return httpServletRequest.getMethod();
	}
	
	/**
	 * 请求方式是否为get
	 * @return 请求方式是否为get
	 * 2017年5月1日
	 * @author MBG
	 */
	@Override
    public boolean isGet() {
		return "GET".equals(getMethod());
	}
	
	/**
	 * 请求方式是否为POST
	 * @return 请求方式是否为POST
	 * 2017年5月1日
	 * @author MBG
	 */
	@Override
    public boolean isPost() {
		return "POST".equals(getMethod());
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
    @Override
    public String getPathInfo() {
    	//在tomcat中，只返回getServletPath()值，不再返回该值
    	return httpServletRequest.getPathInfo(); 
    }
    
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getPathTranslated() {
		return getRealPath(getServletPath());
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getQueryString() {
	    if(queryString==null) {
	        queryString = httpServletRequest.getQueryString();
	        if(queryString==null) {
	            queryString = "";
	        }
	    }
		return queryString;
	}
	
	/**
	 * 设置url中传入的参数序列
	 * @param queryString  url中传入的参数序列
	 * 2015年4月9日
	 * @author 马宝刚
	 */
	public void setQueryString(String queryString) {
	    this.queryString = queryString;
	}
	
	/**
	 * 往现有的url参数字符串中添加新的参数段
	 * @param subQueryString 新的参数段
	 * 2015年4月9日
	 * @author 马宝刚
	 */
	public void addQueryString(String subQueryString) {
	    String qStr = getQueryString(); //当前参数序列
	    if(qStr.startsWith("&")) {
	        qStr = qStr.substring(1);
	    }
	    if(qStr.length()>0) {
	        this.queryString= qStr+"&"+subQueryString;
	    }else {
	        this.queryString= subQueryString;
	    }
	}
	
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getRemoteUser() {
		if(isFake) {
			return ""; //不支持
		}
		return httpServletRequest.getRemoteUser();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getRequestURI() {
		if(isFake) {
			if(contextPath!=null && servletPath!=null) {
				if(contextPath.length()<1 || "/".equals(contextPath)) {
					return servletPath;
				}
				return contextPath+servletPath;
			}
			return ""; //不支持
		}
		return httpServletRequest.getRequestURI();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public StringBuffer getRequestURL() {
		if(isFake) {
			return new StringBuffer(); //不支持，不知道本地服务端口
		}
		//获取返回值
		String reStr = httpServletRequest.getRequestURL().toString();
		int point; //分隔符位置
		
		//从配置文件中获取当前服务的根URL（不包含虚拟路径） 防止请求头被篡改，然后打开别的地址
		if(fe!=null) {
			//从配置文件中获取当前服务根URL
			String baseUrl = fe.getBeanFactory().getConfProp().getParameter("base_host");
			if(baseUrl.length()>0) {
				point = reStr.indexOf("://");
				if(point>-1) {
					reStr = reStr.substring(point+3);
				}
				point = reStr.indexOf("/");
				if(point>-1) {
					reStr = reStr.substring(point);
				}
				return new StringBuffer(baseUrl+reStr);
			}
		}
		
    	/*
    	 * 如果设置了反向代理，外网是https，内网是http，就得
    	 * 获取头信息值，这个信息值时反向代理服务器设置的，
    	 * 外部访问的协议名，如果存在，就用外部的协议名
    	 */
    	String scheme = SString.valueOf(httpServletRequest.getHeader("X-Scheme"));
    	if(scheme.length()<1) {
    		scheme = SString.valueOf(httpServletRequest.getHeader("X-Forwarded-Proto"));
    	}
    	if(scheme.length()>0) {
    		point = reStr.indexOf("://");
    		reStr = scheme+reStr.substring(point);
    	}
		return new StringBuffer(reStr);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getRequestedSessionId() {
	    if(session!=null) {
	        return session.getId();
	    }
		return httpServletRequest.getRequestedSessionId();
	}

	
	/**
	 * 覆盖方法     weblogic返回空（不过已经做了处理）
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getServletPath() {
		if(servletPath==null) {
	    	//全路径
	    	String reStr = httpServletRequest.getRequestURI();
	    	if(reStr!=null && reStr.length()>0) {
		    	//虚拟路径
		    	String contextPath = getContextPath();
		    	if(contextPath!=null && contextPath.length()>0) {
		    		reStr = reStr.substring(contextPath.length());
		    	}
	    	}
	    	servletPath = reStr;
	    	/*
	    	 之前采用的事下面直接获取ServletPath，但是如果是将框架植入现有的程序中
	    	 在web.xml 配置了指定文件夹触发，实际上这个指定的文件夹也是虚拟的路径，
	    	 在获取这个值时，应该也过滤掉这个虚拟路径，所以又启用了上面的代码，屏蔽掉
	    	 该代码
			servletPath = httpServletRequest.getServletPath();
			if(servletPath==null) {
			    //weblogic返回空
				servletPath = httpServletRequest.getRequestURI();
				int point = httpServletRequest.getContextPath().length();
				if(point>1) {
					//如果为 "" 或 "/" 认为没有虚拟路径，不做处理
					servletPath = servletPath.substring(point,servletPath.length());
				}
			}
			*/
		}
		return servletPath;
	}
	
	/**
	 * 设置动作路径
	 * 刘虻
	 * 2010-7-31 下午02:41:26
	 * @param servletPath 动作路径
	 */
	public void setServletPath(String servletPath) {
		this.servletPath = servletPath;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public HttpSession getSession() {
	    if(session!=null) {
	        return session;
	    }
		return httpServletRequest.getSession();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public HttpSession getSession(boolean arg0) {
	    if(session!=null) {
	        return session;
	    }
		return httpServletRequest.getSession(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public Principal getUserPrincipal() {
		if(isFake) {
			return null;
		}
		return httpServletRequest.getUserPrincipal();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public boolean isRequestedSessionIdFromCookie() {
		if(isFake) {
			return false;
		}
	    if(session!=null) {
	        return true;
	    }
		return httpServletRequest.isRequestedSessionIdFromCookie();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public boolean isRequestedSessionIdFromURL() {
		if(isFake) {
			return false;
		}
	    if(session!=null) {
	        return false;
	    }
		return httpServletRequest.isRequestedSessionIdFromURL();
	}

	/**
	 * @deprecated
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
    @Override
    public boolean isRequestedSessionIdFromUrl() {
    	if(isFake) {
    		return false;
    	}
		return httpServletRequest.isRequestedSessionIdFromUrl();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public boolean isRequestedSessionIdValid() {
		if(isFake) {
			return true;
		}
	    if(session!=null) {
	        return true;
	    }
		return httpServletRequest.isRequestedSessionIdValid();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public boolean isUserInRole(String arg0) {
		if(isFake) {
			return true;
		}
		return httpServletRequest.isUserInRole(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public Object getAttribute(String arg0) {
		if(isFake) {
			return fakeAttributeMap.get(arg0);
		}
		return httpServletRequest.getAttribute(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    @SuppressWarnings("unchecked")
	public Enumeration<String> getAttributeNames() {
		if(isFake) {
			return new SEnumeration<String>(fakeAttributeMap);
		}
		return httpServletRequest.getAttributeNames();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getCharacterEncoding() {
		if(characterEncoding==null) {
			characterEncoding = httpServletRequest.getCharacterEncoding();
			if(characterEncoding==null || characterEncoding.length()<1) {
				characterEncoding = "UTF-8";
			}
		}
		return characterEncoding;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public int getContentLength() {
		if(isFake) {
			if(dataBuffers==null) {
				return 0;
			}
			return dataBuffers.length;
		}
		return httpServletRequest.getContentLength();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getContentType() {
		if(contentType==null) {
			contentType = httpServletRequest.getContentType();
		}
		return contentType;
	}

	/**
	 * 覆盖方法
	 * 
	 * 如果设置了缓存（需要在获取数据之前设置）
	 * 会在类中缓存提交的数据
	 * 
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public ServletInputStream getInputStream() throws IOException {
	    if(buffered) {
            if(bufferIs==null) {
                //字节输出流
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                if(getContentLength()>0) {
                    //提交信息读入流
                    InputStream is = httpServletRequest.getInputStream();
                    int    rCount;                  //读取字节数
                    byte[] buffer = new byte[1024]; //缓存
                    //在早期tomcat版本中，如果Content-Type是：application/x-www-form-urlencoded
                    //数据就会被预先读取（数据格式应该为：aaa=bbb&ccc=ddd&eee=fff）到parameterMap中
                    //在新版本的tomcat中，读取到paramegerMap后，缓存流中还会有数据，在下面的循环中
                    //照样可以取出来。但是早起版本在这里就取不出来了
                    while((rCount=is.read(buffer))!=-1) {
                    	bos.write(buffer,0,rCount);
                    }
                }
                dataBuffers = bos.toByteArray();
                bufferIs = new ServletInputStream() {
                    int index = 0; //读取位置指针
                    
                    /**
                     * 读取一个字节
                     * 当读取到末尾后，指针重新指向开头，以便可以重复读取
                     */
                    @Override
                    public int read() throws IOException {
                        if(index>=dataBuffers.length) {
                            return -1;
                        }
                        return dataBuffers[index++] & 0xff;
                    }
                    
                    /**
                     * 覆盖方法
                     */
                    @Override
                    public void reset() {
                        try {
                            super.reset();
                        }catch(Exception e) {}
                        index = 0;
                    }
                    
                    /**
                     * 关闭流（实际上将指针复位）
                     */
                    @Override
                    public void close() {
                        index = 0;
                    }

                    @Override
                    public boolean isFinished() {
                      return index >= dataBuffers.length;
                    }

                    @Override
                    public boolean isReady() {
                      return true;
                    }

                    @Override
                    public void setReadListener(ReadListener arg0) {}
                };
            }
            //为啥要reset，没想明白，干掉
            //else {
            //    bufferIs.reset();
            //}
            return bufferIs;
	    }
	    //请求报文体因为是数据流格式的，获取一次后，无法再次获取（上面提供了缓存功能，不过是用在别处的）
	    //遇到获取请求报文体数据流时发现已经被获取过了，这种情况很头疼，不知道什么时候首次获取的。
	    //于是增加了调试方法
		if(firstGetReqData) {
			firstGetReqData = false;
			if(getSession().getAttribute("_debug_request_")!=null) {
				reqDataTraceInfo = DebugUtil.getStackTraceString(this);
			}
		}else {
			if(reqDataTraceInfo!=null) {
				System.err.println("Is Already getInputStream. Only Get Onece. Trace:\n"+reqDataTraceInfo);
			}else {
				System.err.println("Is Already getInputStream. Only Get Onece. Need Debug For Put The key:[_debug_request_] value:[1] To Session");
			}
		}
	    return httpServletRequest.getInputStream();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getLocalAddr() {
		if(isFake) {
			return "127.0.0.1";
		}
		return httpServletRequest.getLocalAddr();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getLocalName() {
		if(isFake) {
			return "localhost";
		}
		return httpServletRequest.getLocalName();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public int getLocalPort() {
		if(localPort==0) {
			localPort = httpServletRequest.getLocalPort();
		}
		return localPort;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public Locale getLocale() {
		if(locale==null) {
			locale = httpServletRequest.getLocale();
		}
		return locale;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public Enumeration<Locale> getLocales() {
		if(httpServletRequest==null) {
			return null;
		}
		return httpServletRequest.getLocales();
	}

    /**
     * 覆盖方法
     * 刘虻
     * 2010-7-1 下午06:57:50
     */
    @Override
    public String getParameter(String arg0) {
        //获取返回值
        String[] reStrs = getParameterMap().get(arg0);
        if(reStrs==null || reStrs.length<1 || reStrs[0]==null) {
            return "";
        }
        return reStrs[0];
    }
	

    /**
     * 设置传入参数
     * @param key      参数主键
     * @param values    参数值数组
     * 2014年6月12日
     * @author 马宝刚
     */
    @Override
    public void setParameter(String key, String[] values) {
    	getParameterMap().put(key,values);
    }

    /**
     * 设置传入参数
     * @param key      参数主键
     * @param values    参数值数组
     * 2014年6月12日
     * @author 马宝刚
     */
    @Override
    public void setParameter(String key, String values) {
    	getParameterMap().put(key,new String[] {values});
    }
 
     /**
      * 覆盖方法
      * 刘虻
      * 2010-7-1 下午06:57:50
      */
     @Override
     public synchronized Map<String,String[]> getParameterMap() {
         if(parameterMap==null) {
             parameterMap = new WebParameterMap<String,String[]>();
             synchronized (BASIC_AUTH) {
            	//在早起版本tomcat中，在设置缓存时，无法从读入流中获取post上来的数据
            	 //所以加上了(dataBuffers!=null && dataBuffers.length>0)判断是否成功获取到数据
                if(buffered && (dataBuffers!=null && dataBuffers.length>0)) {
                    getParametersFromBuffer();
                }else {
                    parameterMap.putAll(StringUtil.fixQueryStrings(getQueryString()));
                    parameterMap.putAll(httpServletRequest.getParameterMap());
                }
            }
         }
         return parameterMap;
     }

     /**
      * 解析提交参数
      * @author 刘虻
      * 2008-7-1下午01:10:36
      * @param result 参数容器
      * @param query 提交参数字符串
      * @param encoding 参数编码
      * @return 参数容器
      */
     private void parseQueryString(Map<String,String[]> result,String query,String encoding) {
         StringTokenizer st = new StringTokenizer(query, "&");
         while (st.hasMoreTokens()) {
             String pair = st.nextToken();
             int ep = pair.indexOf('=');
             String key = ep > 0 ? pair.substring(0, ep) : pair;
             String value = ep > 0 ? pair.substring(ep + 1) : null;
             try {
                 key = /* URLDecoder. */StringUtil.decode(key,encoding);
                 if (value != null) {
                     value = /* URLDecoder. */StringUtil.decode(value,encoding);
                 }
             } catch (UnsupportedEncodingException uee) {}
             String[] values = result.get(key);
             String[] newValues;
             if (values == null) {
                 newValues = new String[1];
                 newValues[0] = value;
             } else {
                 newValues = new String[values.length + 1];
                 System.arraycopy(values, 0, newValues, 0, values.length);
                 newValues[values.length] = value;
             }
             result.put(key, newValues);
         }
     }
     
     /**
      * 母鸡
      * @author 刘虻
      * 2008-7-9上午02:35:22
      * @return
      */
     private void  getParametersFromBuffer() {
         String method = getMethod(); //提交类型
         String reqQuery = getQueryString(); //获取url上拼装的参数
         String enc = getCharacterEncoding(); //编码
         if (reqQuery != null) {
             try {
                 parseQueryString(parameterMap,reqQuery,enc);
             } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
             }
         }
         //内容类型
         String contentType = SString.valueOf(getContentType()).toLowerCase();
          if ("POST".equals(method) && contentType.indexOf("xml")<0 && contentType.indexOf("json")<0) {
              if(dataBuffers!=null && dataBuffers.length>0) {
                  try {
                      parseQueryString(parameterMap,new String(dataBuffers,enc), enc);
                  }catch(Exception e) {
                      e.printStackTrace();
                  }
              }
          }
     }
     
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    @SuppressWarnings("unchecked")
	public Enumeration<String> getParameterNames() {
		if(isFake) {
			return new SEnumeration<String>(parameterMap);
		}
		return httpServletRequest.getParameterNames();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String[] getParameterValues(String arg0) {
		return getParameterMap().get(arg0);
	}
	
	/**
	 * 是否缓存提交值
	 * @return 是否缓存提交值
	 * 2014年9月5日
	 * @author 马宝刚
	 */
	@Override
    public boolean isBuffered() {
	    return buffered;
	}
	
	/**
	 * 设置缓存提交值
	 * 2014年9月5日
	 * @author 马宝刚
	 */
	@Override
    public void setBuffered() {
	    this.buffered = true;
		if(parameterMap!=null && parameterMap.size()>0) {
			//没有必要这么提示，已经执行过就已经执行过，下次直接走缓存
			//System.err.println("*********The Request Has Been Get Info,Can't Set Buffered*********\n"+DebugUtil.getMapValue(parameterMap));
			return;
		}else {
			//设置为空，下次获取数据时，会直接从缓存中获取数据
			parameterMap = null;
		}
	    //缓存数据
	    try {
	        getInputStream();
	    }catch(Exception e) {
	        e.printStackTrace();
	    }
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getProtocol() {
		if(protocol==null) {
			protocol = httpServletRequest.getProtocol();
		}
		return protocol;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public BufferedReader getReader() throws IOException {
		if(isFake) {
			return null;
		}
		return httpServletRequest.getReader();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
    @Override
    public String getRealPath(String arg0) {
		return webBasePath+arg0;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getRemoteAddr() {
		if(isFake) {
			return "127.0.0.1";
		}
		return httpServletRequest.getRemoteAddr();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getRemoteHost() {
		if(isFake) {
			return "localhost";
		}
		return httpServletRequest.getRemoteHost();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public int getRemotePort() {
		if(isFake) {
			return 0; //不支持
		}
		return httpServletRequest.getRemotePort();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public RequestDispatcher getRequestDispatcher(String arg0) {
		if(isFake) {
			return null;
		}
		return httpServletRequest.getRequestDispatcher(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getScheme() {
		if(scheme==null) {
			scheme = httpServletRequest.getScheme();
		}
		return scheme;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public String getServerName() {
		if(isFake) {
			return "localhost";
		}
		return httpServletRequest.getServerName();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public int getServerPort() {
		if(isFake) {
			return localPort;
		}
		return httpServletRequest.getServerPort();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public boolean isSecure() {
		if(isFake) {
			return secure;
		}
		return httpServletRequest.isSecure();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public void removeAttribute(String arg0) {
		if(isFake) {
			fakeAttributeMap.remove(arg0);
			return;
		}
		httpServletRequest.removeAttribute(arg0);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public void setAttribute(String arg0, Object arg1) {
		if(isFake) {
			fakeAttributeMap.put(arg0,arg1);
			return;
		}
		httpServletRequest.setAttribute(arg0,arg1);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-7-1 下午06:57:50
	 */
	@Override
    public void setCharacterEncoding(String arg0)
			throws UnsupportedEncodingException {
		characterEncoding = arg0;
		try {
			//早期的tomcat报空指针
			httpServletRequest.setCharacterEncoding(arg0);
		}catch(Exception e) {}
	}

	
	/**
	 * 设置是否禁止使用页面请求外壳（主要用于过滤）
	 * 刘虻
	 * 2010-8-2 下午03:25:07
	 * @param disabled 是否禁止使用页面请求外壳
	 */
	@Override
    public void setDisabledWrapper(boolean disabled) {
		if(!isFake && httpServletRequest instanceof SecureRequestWrapper) {
			((SecureRequestWrapper)httpServletRequest).setDisabled(disabled);
			parameterMap = null;
		}
	}
	
	/**
	 * 获取客户端IP地址信息 简称 ：cip
	 * @return 客户端IP地址信息
	 * 2014年4月15日
	 * @author 马宝刚
	 */
    @Override
    public String getClientIP() {
    	return cip();
    }
    
	/**
	 * 获取客户端IP地址信息 全称：getClientIP
	 * @return 客户端IP地址信息
	 * 2014年4月15日
	 * @author 马宝刚
	 */
    @Override
    public String cip() {
    	if(isFake) {
    		return "127.0.0.1";
    	}
		String ip = SString.valueOf(getHeader("x-forwarded-for"));  
		if(ip.length()<1 || "unknown".equalsIgnoreCase(ip)) {  
			ip = SString.valueOf(getHeader("Proxy-Client-IP"));  
		}
		if(ip.length()<1 || "unknown".equalsIgnoreCase(ip)) {  
			ip = SString.valueOf(getHeader("WL-Proxy-Client-IP"));  
		}  
		if( ip.length()<1 || "unknown".equalsIgnoreCase(ip)) {  
			ip = SString.valueOf(getRemoteAddr());  
		}  
		int point = ip.indexOf(","); //分隔符，如果返回一串用逗号分割的ip地址，只取第一个
		if(point>0) {
			ip = ip.substring(0,point).trim();
		}
		return ip;  
	}
    
    

    @Override
    public boolean authenticate(HttpServletResponse arg0) throws IOException,ServletException {
    	if(httpServletRequest==null) {
    		return false;
    	}
        return httpServletRequest.authenticate(arg0);
    }

    @Override
    public Part getPart(String arg0) throws IOException, IllegalStateException,ServletException {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.getPart(arg0);
    }

    @Override
    public Collection<Part> getParts() throws IOException,IllegalStateException, ServletException {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.getParts();
    }

    @Override
    public void login(String arg0, String arg1) throws ServletException {
    	if(isFake) {
    		return;
    	}
        httpServletRequest.login(arg0,arg1);
    }

    @Override
    public void logout() throws ServletException {
    	if(isFake) {
    		return;
    	}
        httpServletRequest.logout();
    }

    @Override
    public AsyncContext getAsyncContext() {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.getAsyncContext();
    }

    @Override
    public DispatcherType getDispatcherType() {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.getDispatcherType();
    }

    @Override
    public ServletContext getServletContext() {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.getServletContext();
    }

    @Override
    public boolean isAsyncStarted() {
    	if(isFake) {
    		return false;
    	}
        return httpServletRequest.isAsyncStarted();
    }

    @Override
    public boolean isAsyncSupported() {
    	if(isFake) {
    		return false;
    	}
        return httpServletRequest.isAsyncSupported();
    }

    @Override
    public AsyncContext startAsync() {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.startAsync();
    }

    @Override
    public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1) {
    	if(isFake) {
    		return null;
    	}
        return httpServletRequest.startAsync(arg0,arg1);
    }

    @Override
    public <T extends HttpUpgradeHandler> T upgrade(Class<T> arg0) throws IOException, ServletException {
      return null;
    }
    
    
    /**
     * 设置网站根路径
     * @param basePath 网站根路径
     * 2015年4月1日
     * @author 马宝刚
     */
    public void setWebBasePath(String basePath) {
        this.webBasePath = basePath;
    }
    
    /**
     * 获取网站根路径
     * @return 网站根路径
     * 2016年3月11日
     * @author 马宝刚
     */
    @Override
    public String getWebBasePath() {
        return webBasePath;
    }
    
    
	/**
	 * 克隆一个同样值的对象（主要用于内部调用其它动作）
	 * @return 克隆一个同样值的对象
	 * 2016年11月21日
	 * @author MBG
	 */
	@Override
    public IFakeRequest clone() {
		//构建返回值
		return new HttpServletRequestImpl(this,fe,true);
	}
	
	/**
	 * 构造一个新的空的类实例 
	 * @return  新的空的类实例 
	 * 2016年11月21日
	 * @author MBG
	 */
	public static IFakeRequest newInstance(IRequest request,FilterExplorer fe) {
		//构建返回值
		HttpServletRequestImpl res = new HttpServletRequestImpl(request,fe,true);
		if(request!=null) {
			res.setSession(new ServletSession(request.getSession())); //设置会话信息
		}
		return res;
	}
	
	/**
	 * 设置请求方式
	 * @param method 请求方式
	 * 2016年11月24日
	 * @author MBG
	 */
	@Override
    public void setMethod(String method) {
		this.method = method;
	}
	
	/**
	 * 设置路径信息
	 * @param webBasePath  网站根路径（文件路径）
	 * @param contextPath  上下文路径  /网站虚拟路径
	 * @param servletPath  纯动作路径  /文件夹/文件     weblogic返回空
	 * @param queryString  url中提交的参数
	 * 2016年11月24日
	 * @author MBG
	 */
	@Override
    public void setUrlInfo(String webBasePath, String contextPath, String servletPath, String queryString) {
		if(servletPath!=null) {
			//参数分隔符
			int point = servletPath.indexOf("?");
			if(point>0) {
				if(queryString==null || queryString.length()<1) {
					queryString = servletPath.substring(point+1);
				}else {
					queryString += "&"+servletPath.substring(point+1);
				}
				servletPath = servletPath.substring(0,point);
			}
		}
		this.webBasePath = webBasePath;
		this.contextPath = contextPath;
		this.servletPath = servletPath;
		this.queryString = queryString;
	}
	
	/**
	 * 设置内容类型
	 * @param contentType 内容类型
	 * 2016年11月24日
	 * @author MBG
	 */
	@Override
    public void setContentType(String contentType) {
		this.contentType = contentType;
	}
	
	
	/**
	 * 设置提交的数据
	 * @param data 提交的数据
	 * 2016年11月24日
	 * @author MBG
	 */
	@Override
    public void setPostData(Object data) {
		if(data==null) {
			return;
		}
		buffered = true;
		if(data instanceof String) {
			contentType = "application/x-www-form-urlencoded";
			getParameterMap().putAll(StringUtil.fixQueryStrings((String)data));
		}else {
			if(data instanceof Json) {
				contentType = "application/json; charset=UTF-8";
				dataBuffers = data.toString().getBytes();
			}else if(data instanceof IViewHandler) {
				contentType = "text/xml; charset=UTF-8";
				dataBuffers = ((IViewHandler)data).getNodeBody().getBytes();
			}else {
				contentType = "application/x-www-form-urlencoded";
				//不认传入参数 类型
				dataBuffers = new byte[0];
			}
		}
	}

	
	/**
	 * 设置方案 http 还是 https
	 * @param scheme 方案
	 * 2016年11月24日
	 * @author MBG
	 */
	@Override
    public void setScheme(String scheme) {
		this.scheme = scheme;
	}
	
	/**
	 * 覆盖方法
	 */
	@Override
    public String toString() {
		//构建返回值
		String reStr = getClass().getName()+"_"+hashCode();
		if(isFake) {
			reStr += " FAKE!!";
		}
		if(httpServletRequest!=null) {
			reStr += "\nURI:["+httpServletRequest.getRequestURI()+"]";
			reStr += "\nQueryString:["+httpServletRequest.getQueryString()+"]";
			reStr += "\nMethod:["+httpServletRequest.getMethod()+"]";
			reStr += "\nParameter:["+DebugUtil.getMapValue(httpServletRequest.getParameterMap())+"]";
			reStr += "\nRemoteAddr:["+httpServletRequest.getRemoteAddr()+"]";
			reStr += "\nRemoteHost:["+httpServletRequest.getRemoteHost()+"]";
		}
		return reStr;
	}


	/**
	 * 设置头信息
	 * @param key   头主键
	 * @param value 对应值
	 * 2016年12月11日
	 * @author MBG
	 */
	@Override
	public void setHeader(String key, String value) {
		headerMap.put(key,value);
	}
	
	
	/**
	 * 是否为内置服务器响应的请求
	 * @return 是否为内置服务器响应的请求
	 * 2017年8月31日
	 * @author MBG
	 */
	@Override
    public boolean isNativeServer() {
		if(httpServletRequest==null) {
			return false;
		}
		if(httpServletRequest instanceof SecureRequestWrapper 
				&&  ((SecureRequestWrapper)httpServletRequest).getKernel() instanceof ServeConnection.Request) {
			return ((ServeConnection.Request)((SecureRequestWrapper)httpServletRequest).getKernel()).isNativeServ();
		}
		return false;
	}

	/**
	 * 覆盖方法 Tomcat8
	 */
	public String changeSessionId() {
		return null;
	}

	/**
	 * 覆盖方法 Tomcat8
	 */
	public long getContentLengthLong() {
		return 0;
	}

	/**
	 * 获取请求URL中提交的参数容器
	 * @return 请求URL中提交的参数容器
	 * 2018年3月2日
	 * @author MBG
	 */
	@Override
	public Map<String, String> getUrlParameterMap() {
		if(urlParameterMap==null) {
			urlParameterMap = StringUtil.fixQueryString(getQueryString());
		}
		return urlParameterMap;
	}


	/**
	 * 从请求URL中获取指定的参数值
	 * @param key 参数主键
	 * @return    参数值
	 * 2018年3月2日
	 * @author MBG
	 */
	@Override
	public String getUrlParameter(String key) {
		return SString.valueOf(getUrlParameterMap().get(key));
	}
}
